/* 
* Copyright (c) 2021 Talkweb Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. 
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cmsis_os2.h"
#include "ohos_init.h"

#include "MQTTClient.h"
#include "wifi_connect.h"

static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];

// 默认WiFi名和密码
#define SELECT_WIFI_SSID "111"
#define SELECT_WIFI_PASSWORD "0987654321"

Network network;

/**
 * @brief 订阅主题处理消息函数
 * @param MessageData 消息数据
 * @return 
 */ 
void MessageArrived(MessageData* data)
{
    printf("Message arrived on topic %.*s: %.*s\n", 
            data->topicName->lenstring.len, data->topicName->lenstring.data,
            data->message->payloadlen, data->message->payload);
}

/**
 * @brief MQTT任务处理 
 * @param void
 * @return void
 */
static void MQTTDemoTask(void)
{
    // 连接WIFI
    WifiConnect(SELECT_WIFI_SSID, SELECT_WIFI_PASSWORD);
    printf("Starting ...\n");
    int rc, count = 0;
    MQTTClient client;

    // 初始化网络参数
    NetworkInit(&network);
    printf("NetworkConnect  ...\n");
begin:
    // 连接服务器网络
    NetworkConnect(&network, "192.168.153.192", 61613); // 参考README.md修改地址和端口
    printf("MQTTClientInit  ...\n");
    // 初始化客户端
    MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

    // 连接参数
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 
    // 客户ID，唯一
    data.clientID.cstring= "Talkweb";   
    // 不使用临终遗言
    data.willFlag = 0; 
    // MQTT版本号
    data.MQTTVersion = 3; 
    // 保存存活时间
    data.keepAliveInterval = 0; 
    // 重新连接后是否清除以前的信息 0表示不清除，1表示重连清除
    data.cleansession = 1;
    // 服务器用户名
    data.username.cstring = "admin";
    // 服务器用户密码
    data.password.cstring = "password";

    printf("MQTTConnect  ...\n");
    // 登录服务器
    rc = MQTTConnect(&client, &data);
    // 失败处理
    if (rc != 0)
    {
        printf("MQTTConnect: %d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        osDelay(200);
        goto begin;
    }

    printf("MQTTSubscribe  ...\n");
    // 订阅主题，并绑定回调函数处理接收到的消息
    rc = MQTTSubscribe(&client, "pubtopic", 2, MessageArrived);
    // 订阅失败处理
    if (rc != 0)
    {
        printf("MQTTSubscribe: %d\n", rc);
        osDelay(200);
        goto begin;
    }
    while (++count)
    {
        MQTTMessage message;
        // 发布的内容
        char payload[] = {"{\"name\": \"Talkweb\",\"url\": \"https://www.talkweb.com.cn/\"}"};
        // 仅一次
        message.qos = 2;
        message.retained = 0;
        message.payload = payload;
        message.payloadlen = strlen(payload);
        // 发布
        if ((rc = MQTTPublish(&client, "pubtopic", &message)) != 0)
        {
            printf("Return code from MQTT publish is %d\n", rc);
            NetworkDisconnect(&network);
            MQTTDisconnect(&client);
            count = 0;
            goto begin;
        }
        osDelay(100);
    }
}

// MQTTDemo教程
static void MQTTDemo(void)
{
    osThreadAttr_t attr;

    attr.name = "MQTTDemoTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = osPriorityNormal;

    if (osThreadNew((osThreadFunc_t)MQTTDemoTask, NULL, &attr) == NULL)
    {
        printf("[MQTT_Demo] Failed to create MQTTDemoTask!\n");
    }
}

APP_FEATURE_INIT(MQTTDemo);